#include "SemanticNodeModel.h"

#include "main2.h"

/**
 *  @fn	SemanticNodeModel::SemanticNodeModel(const SyntaxTreeNode *syntaxNode,
 *  	SemanticNode *parent)
 *
 *  @brief	Constructor.
 *
 *  @author	Nikola Novak
 *  @date	6/23/2009
 *
 *  @param	syntaxNode	If non-null, the syntax node.
 *  @param	parent	If non-null, the parent.
 */
SemanticNodeModel::SemanticNodeModel(const SyntaxTreeNode *syntaxNode, SemanticNode *parent) : priv(true), SemanticNode(parent) {
	if (syntaxNode->Nodes->GetData(0)->Production == Gr_ModelMod__public) priv = false;
	name = flattenNamePeriodAdd(*syntaxNode->Nodes->GetData(2));
	if (syntaxNode->Nodes->GetData(6)->Nodes->GetCount() > 0) {
		inLabels = flattenLabelList(syntaxNode->Nodes->GetData(6)->Nodes->GetData(2));
	} else inLabels.push_back("0"); // ako in blok nije definiram dodajem implicitni ulaz (0)
	if (syntaxNode->Nodes->GetData(7)->Nodes->GetCount() > 0) {
		outLabels = flattenLabelList(syntaxNode->Nodes->GetData(7)->Nodes->GetData(2));
	} else outLabels.push_back("0"); // ako out blok nije definiran dodajem implicitni izlaz (0)
	usingDirectives = new UsingDirectives(syntaxNode->Nodes->GetData(9)->Nodes->GetData(0), this);
}
/**
 *  @fn	std::string SemanticNodeModel::getName(void)
 *
 *  @brief	Gets the name.
 *
 *  @author	Nikola Novak
 *  @date	6/23/2009
 *
 *  @return	The name.
 */
std::string SemanticNodeModel::getName(void) {
	return name;
}
/**
 *  @fn	std::string SemanticNodeModel::toDebugString(int tab)
 *
 *  @brief	Converts a tab to a debug string.
 *
 *  @author	Nikola Novak
 *  @date	6/23/2009
 *
 *  @param	tab	The tab.
 *
 *  @return	This object as a std::string.
 */
std::string SemanticNodeModel::toDebugString(int tab) {
	std::ostringstream res;
	for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;
	if (priv) res << "private";
	else res << "public";
	res << " model " << name << " (" << std::endl;
	for (std::vector<SemanticNodeField *>::iterator i = parameters.begin(); i != parameters.end(); ++i) res << (*i)->toDebugString(tab + 1);
	for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;
	res << ") in (";
	for (std::vector<std::string>::iterator i = inLabels.begin(); i != inLabels.end(); ) {
		std::string tp = *i;
		if (*i == "0") tp = "default";
		res << tp;
		if (++i != inLabels.end()) res << ", ";
	}
	res << ") out (";
	for (std::vector<std::string>::iterator i = outLabels.begin(); i != outLabels.end(); ) {
		std::string tp = *i;
		if (*i == "0") tp = "default";
		res << tp;
		if (++i != outLabels.end()) res << ", ";
	}
	res << ") ";
	res << usingDirectives->toDebugString(0);
	for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;
	res << " define {" << std::endl;
	for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;
	res << " fields:" << std::endl;
	for (std::vector<SemanticNodeField *>::iterator i = fields.begin(); i != fields.end(); ++i) res << (*i)->toDebugString(tab + 1);
	for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;
	res << " properties:" << std::endl;
	for (std::vector<SemanticNodeProperty *>::iterator i = properties.begin(); i != properties.end(); ++i) res << (*i)->toDebugString(tab + 1);
	for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;
	res << " methods:" << std::endl;
	for (std::vector<SemanticNodeMethod *>::iterator i = methods.begin(); i != methods.end(); ++i) res << (*i)->toDebugString(tab + 1);
	for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;
	res << " enums:" << std::endl;
	for (std::vector<SemanticNodeEnum *>::iterator i = enums.begin(); i != enums.end(); ++i) res << (*i)->toDebugString(tab + 1);
	for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;
	res << "}" << std::endl;
	//for (std::vector<SemanticNodeBlockGenerate *>::iterator i = generators.begin(); i != generators.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockTerminate *>::iterator i = terminators.begin(); i != terminators.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockAdvance *>::iterator i = advancers.begin(); i != advancers.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockEnter *>::iterator i = entrants.begin(); i != entrants.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockLeave *>::iterator i = leavers.begin(); i != leavers.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockSeize *>::iterator i = seizers.begin(); i != seizers.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockRelease *>::iterator i = releasers.begin(); i != releasers.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockInqueue *>::iterator i = inqueuers.begin(); i != inqueuers.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockOutqueue *>::iterator i = outqueuers.begin(); i != outqueuers.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockArrive *>::iterator i = arrivals.begin(); i != arrivals.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockDepart *>::iterator i = departures.begin(); i != departures.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockModelInstance *>::iterator i = modelInstances.begin(); i != modelInstances.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockGoto *>::iterator i = gotos.begin(); i != gotos.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockIf *>::iterator i = ifs.begin(); i != ifs.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockWait *>::iterator i = waiters.begin(); i != waiters.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockJoinGroup *>::iterator i = groupJoiners.begin(); i != groupJoiners.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockLeaveGroup *>::iterator i = groupLeavers.begin(); i != groupLeavers.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockCreate *>::iterator i = creators.begin(); i != creators.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockSplit *>::iterator i = splitters.begin(); i != splitters.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockGather *>::iterator i = gatherers.begin(); i != gatherers.end(); ++i) res << (*i)->toDebugString(tab + 1);
	//for (std::vector<SemanticNodeBlockExecute *>::iterator i = executors.begin(); i != executors.end(); ++i) res << (*i)->toDebugString(tab + 1);
	for (std::vector<SemanticNode *>::iterator i = blockOrder.begin(); i != blockOrder.end(); ++i) res << (*i)->toDebugString(tab + 1);
	return res.str();
}
/**
 *  @fn	std::vector<std::string> SemanticNodeModel::flattenLabelList(const SyntaxTreeNode *labelLis
 *  	tNode)
 *
 *  @brief	Flattens label list.
 *
 *  @author	Nikola Novak
 *  @date	6/23/2009
 *
 *  @param	labelListNode	If non-null, the label list node.
 *
 *  @return	.
 */
std::vector<std::string> SemanticNodeModel::flattenLabelList(const SyntaxTreeNode *labelListNode) {
	std::vector<std::string> result;
	if (labelListNode->Nodes->GetCount() == 0) return result;
	else {
		if (labelListNode->Production == Gr_LabelList__default_Labels) result.push_back("0");
		else if (labelListNode->Production == Gr_LabelList__NAME_Labels)
		{
			LexicUnit lu = CompilerData->Units->GetLexicUnit(labelListNode->Nodes->GetData(0)->LexUnitID);
			result.push_back(CompilerData->Units->GetLexicUnitString(&lu));
		}
		for (int x = 0; x < labelListNode->Nodes->GetData(1)->Nodes->GetCount(); ++x) {
			const SyntaxTreeNode *cNode = labelListNode->Nodes->GetData(1)->Nodes->GetData(x);
			LexicUnit lu = CompilerData->Units->GetLexicUnit(cNode->Nodes->GetData(1)->LexUnitID);
			result.push_back(CompilerData->Units->GetLexicUnitString(&lu));
		}
	}
	return result;
}
/**
 *  @fn	void SemanticNodeModel::addParameters(std::vector<SemanticNodeField*> params)
 *
 *  @brief	Adds parameters.
 *
 *  @author	Nikola Novak
 *  @date	6/23/2009
 *
 *  @param	params	If non-null, options for controlling the operaation.
 */
void SemanticNodeModel::addParameters(std::vector<SemanticNodeField *> params) {
	for (std::vector<SemanticNodeField *>::iterator i = params.begin(); i != params.end(); ++i) parameters.push_back(*i);
}
/**
 *  @fn	void SemanticNodeModel::addFields(std::vector<SemanticNodeField*> fieldNodes)
 *
 *  @brief	Adds fields.
 *
 *  @author	Nikola Novak
 *  @date	6/23/2009
 *
 *  @param	fieldNodes	If non-null, field nodes.
 */
void SemanticNodeModel::addFields(std::vector<SemanticNodeField *> fieldNodes) {
	for (std::vector<SemanticNodeField *>::iterator i = fieldNodes.begin(); i != fieldNodes.end(); ++i) fields.push_back(*i);
}
/**
 *  @fn	void SemanticNodeModel::addField(SemanticNodeField *fieldNode)
 *
 *  @brief	Adds a field.
 *
 *  @author	Nikola Novak
 *  @date	9/22/2009
 *
 *  @param	fieldNode	If non-null, the field node.
 */
void SemanticNodeModel::addField(SemanticNodeField *fieldNode) {
	fields.push_back(fieldNode);
}
/**
 *  @fn	void SemanticNodeModel::addProperty(SemanticNodeProperty *propertyNode)
 *
 *  @brief	Adds a property.
 *
 *  @author	Nikola Novak
 *  @date	9/22/2009
 *
 *  @param	propertyNode	If non-null, the property node.
 */
void SemanticNodeModel::addProperty(SemanticNodeProperty *propertyNode) {
	properties.push_back(propertyNode);
}
/**
 *  @fn	void SemanticNodeModel::addMethod(SemanticNodeMethod *methodNode)
 *
 *  @brief	Adds a method.
 *
 *  @author	Nikola Novak
 *  @date	9/22/2009
 *
 *  @param	methodNode	If non-null, the method node.
 */
void SemanticNodeModel::addMethod(SemanticNodeMethod *methodNode) {
	methods.push_back(methodNode);
}
/**
 *  @fn	void SemanticNodeModel::addEnum(SemanticNodeEnum *enumNode)
 *
 *  @brief	Adds an enum.
 *
 *  @author	Nikola Novak
 *  @date	9/22/2009
 *
 *  @param	enumNode	If non-null, the enum node.
 */
void SemanticNodeModel::addEnum(SemanticNodeEnum *enumNode) {
	enums.push_back(enumNode);
}
/**
 *  @fn	void SemanticNodeModel::addBlockTerminate(SemanticNodeBlockTerminate *terminator)
 *
 *  @brief	Adds a terminate block.
 *
 *  @author	Nikola Novak
 *  @date	6/23/2009
 *
 *  @param	terminator	If non-null, the terminator.
 */
void SemanticNodeModel::addBlockTerminate(SemanticNodeBlockTerminate *terminator) {
	terminators.push_back(terminator);
	blockOrder.push_back(terminator);
}
/**
 *  @fn	void SemanticNodeModel::addBlockGenerate(SemanticNodeBlockGenerate *generator)
 *
 *  @brief	Adds a block generate.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	generator	If non-null, the generator.
 */
void SemanticNodeModel::addBlockGenerate(SemanticNodeBlockGenerate *generator) {
	generators.push_back(generator);
	blockOrder.push_back(generator);
}
/**
 *  @fn	void SemanticNodeModel::addBlockAdvance(SemanticNodeBlockAdvance *advancer)
 *
 *  @brief	Adds a block advance.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	advancer	If non-null, the advancer.
 */
void SemanticNodeModel::addBlockAdvance(SemanticNodeBlockAdvance *advancer) {
	advancers.push_back(advancer);
	blockOrder.push_back(advancer);
}
/**
 *  @fn	void SemanticNodeModel::addBlockEnter(SemanticNodeBlockEnter *entrant)
 *
 *  @brief	Adds a block enter.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	entrant	If non-null, the entrant.
 */
void SemanticNodeModel::addBlockEnter(SemanticNodeBlockEnter *entrant) {
	entrants.push_back(entrant);
	blockOrder.push_back(entrant);
}
/**
 *  @fn	void SemanticNodeModel::addBlockLeave(SemanticNodeBlockLeave *leaver)
 *
 *  @brief	Adds a block leave.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	leaver	If non-null, the leaver.
 */
void SemanticNodeModel::addBlockLeave(SemanticNodeBlockLeave *leaver) {
	leavers.push_back(leaver);
	blockOrder.push_back(leaver);
}
/**
 *  @fn	void SemanticNodeModel::addBlockSeize(SemanticNodeBlockSeize *seizer)
 *
 *  @brief	Adds a block seize.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	seizer	If non-null, the seizer.
 */
void SemanticNodeModel::addBlockSeize(SemanticNodeBlockSeize *seizer) {
	seizers.push_back(seizer);
	blockOrder.push_back(seizer);
}
/**
 *  @fn	void SemanticNodeModel::addBlockRelease(SemanticNodeBlockRelease *releaser)
 *
 *  @brief	Adds a block release.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	releaser	If non-null, the releaser.
 */
void SemanticNodeModel::addBlockRelease(SemanticNodeBlockRelease *releaser) {
	releasers.push_back(releaser);
	blockOrder.push_back(releaser);
}
/**
 *  @fn	void SemanticNodeModel::addBlockInqueue(SemanticNodeBlockInqueue *inqueuer)
 *
 *  @brief	Adds a block inqueue.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	inqueuer	If non-null, the inqueuer.
 */
void SemanticNodeModel::addBlockInqueue(SemanticNodeBlockInqueue *inqueuer) {
	inqueuers.push_back(inqueuer);
	blockOrder.push_back(inqueuer);
}
/**
 *  @fn	void SemanticNodeModel::addBlockOutqueue(SemanticNodeBlockOutqueue *outqueuer)
 *
 *  @brief	Adds a block outqueue.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	outqueuer	If non-null, the outqueuer.
 */
void SemanticNodeModel::addBlockOutqueue(SemanticNodeBlockOutqueue *outqueuer) {
	outqueuers.push_back(outqueuer);
	blockOrder.push_back(outqueuer);
}
/**
 *  @fn	void SemanticNodeModel::addBlockArrive(SemanticNodeBlockArrive *arrivee)
 *
 *  @brief	Adds a block arrive.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	arrivee	If non-null, the arrivee.
 */
void SemanticNodeModel::addBlockArrive(SemanticNodeBlockArrive *arrivee) {
	arrivals.push_back(arrivee);
	blockOrder.push_back(arrivee);
}
/**
 *  @fn	void SemanticNodeModel::addBlockDepart(SemanticNodeBlockDepart *departure)
 *
 *  @brief	Adds a block depart.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	departure	If non-null, the departure.
 */
void SemanticNodeModel::addBlockDepart(SemanticNodeBlockDepart *departure) {
	departures.push_back(departure);
	blockOrder.push_back(departure);
}
/**
 *  @fn	void SemanticNodeModel::addBlockModelInstance(SemanticNodeBlockModelInstance *modelInstance
 *  	)
 *
 *  @brief	Adds a block model instance.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	modelInstance	If non-null, the model instance.
 */
void SemanticNodeModel::addBlockModelInstance(SemanticNodeBlockModelInstance *modelInstance) {
	modelInstances.push_back(modelInstance);
	blockOrder.push_back(modelInstance);
}
/**
 *  @fn	void SemanticNodeModel::addBlockGoto(SemanticNodeBlockGoto *gotoer)
 *
 *  @brief	Adds a block goto.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	gotoer	If non-null, the gotoer.
 */
void SemanticNodeModel::addBlockGoto(SemanticNodeBlockGoto *gotoer) {
	gotos.push_back(gotoer);
	blockOrder.push_back(gotoer);
}
/**
 *  @fn	void SemanticNodeModel::addBlockIf(SemanticNodeBlockIf *ifer)
 *
 *  @brief	Adds a block if.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	ifer	If non-null, the ifer.
 */
void SemanticNodeModel::addBlockIf(SemanticNodeBlockIf *ifer) {
	ifs.push_back(ifer);
	blockOrder.push_back(ifer);
}
/**
 *  @fn	void SemanticNodeModel::addBlockWait(SemanticNodeBlockWait *waiter)
 *
 *  @brief	Adds a block wait.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	waiter	If non-null, the waiter.
 */
void SemanticNodeModel::addBlockWait(SemanticNodeBlockWait *waiter) {
	waiters.push_back(waiter);
	blockOrder.push_back(waiter);
}
/**
 *  @fn	void SemanticNodeModel::addBlockJoinGroup(SemanticNodeBlockJoinGroup *groupJoiner)
 *
 *  @brief	Adds a block join group.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	groupJoiner	If non-null, the group joiner.
 */
void SemanticNodeModel::addBlockJoinGroup(SemanticNodeBlockJoinGroup *groupJoiner) {
	groupJoiners.push_back(groupJoiner);
	blockOrder.push_back(groupJoiner);
}
/**
 *  @fn	void SemanticNodeModel::addBlockLeaveGroup(SemanticNodeBlockLeaveGroup *groupLeaver)
 *
 *  @brief	Adds a block leave group.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	groupLeaver	If non-null, the group leaver.
 */
void SemanticNodeModel::addBlockLeaveGroup(SemanticNodeBlockLeaveGroup *groupLeaver) {
	groupLeavers.push_back(groupLeaver);
	blockOrder.push_back(groupLeaver);
}
/**
 *  @fn	void SemanticNodeModel::addBlockCreate(SemanticNodeBlockCreate *creator)
 *
 *  @brief	Adds a block create.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	creator	If non-null, the creator.
 */
void SemanticNodeModel::addBlockCreate(SemanticNodeBlockCreate *creator) {
	creators.push_back(creator);
	blockOrder.push_back(creator);
}
/**
 *  @fn	void SemanticNodeModel::addBlockSplit(SemanticNodeBlockSplit *splitter)
 *
 *  @brief	Adds a block split.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	splitter	If non-null, the splitter.
 */
void SemanticNodeModel::addBlockSplit(SemanticNodeBlockSplit *splitter) {
	splitters.push_back(splitter);
	blockOrder.push_back(splitter);
}
/**
 *  @fn	void SemanticNodeModel::addBlockGather(SemanticNodeBlockGather *gatherer)
 *
 *  @brief	Adds a block gather.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	gatherer	If non-null, the gatherer.
 */
void SemanticNodeModel::addBlockGather(SemanticNodeBlockGather *gatherer) {
	gatherers.push_back(gatherer);
	blockOrder.push_back(gatherer);
}
/**
 *  @fn	void SemanticNodeModel::addBlockExecute(SemanticNodeBlockExecute *executor)
 *
 *  @brief	Adds a block execute.
 *
 *  @author	Nikola Novak
 *  @date	6/24/2009
 *
 *  @param	executor	If non-null, the executor.
 */
void SemanticNodeModel::addBlockExecute(SemanticNodeBlockExecute *executor) {
	executors.push_back(executor);
	blockOrder.push_back(executor);
}
